using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using Xfinity.Levels;
using Microsoft.Xna.Framework;
using Xfinity.AI.Entities;
using Xfinity.Scripting;
using System.Reflection;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using Xfinity.AI;
using Xfinity.Engine.SceneGraph;

namespace Xfinity.GameEditor
{
    public partial class Nebulae : Form
    {
        private Level level;

        public Level Level
        {
            get { return level; }
            set { level = value; }
        }
        private static FileStream weaponDatabaseStream = File.Open(@".\Default Weapons.nlx", FileMode.OpenOrCreate);

        /// <summary>
        /// Gets or sets the weapon database stream.
        /// </summary>
        /// <value>The weapon database stream.</value>
        public static FileStream WeaponDatabaseStream
        {
            get { weaponDatabaseStream.Position = 0; return weaponDatabaseStream; }
            set { weaponDatabaseStream = value; }
        }


        private OptionsPage options = new OptionsPage();
        private Guid designerID;
        string fileName;
        
        XmlSerializer xmls;
        private Microsoft.Xna.Framework.TargetPlatform platform;
        public OptionsPage OptionsPage
        {
            get { return options; }
        }
        private VistaApi.Margins margins;
        private System.Drawing.Rectangle topRect = System.Drawing.Rectangle.Empty;
        Color transparencyKey = Color.FromArgb(255, 2, 3, 4);
        public Nebulae()
        {
            InitializeComponent();
            try
            {
                 xmls = new XmlSerializer(typeof(Level), new Type[] { typeof(List<PhysicalEntity>), typeof(List<LogicalEntity>), typeof(Agent), typeof(Squad), typeof(SquadCollection), typeof(AgentCollection), typeof(SceneGraph) });
            }
            catch (InvalidOperationException e)
            {
                InvalidOperationException ex = e;
                throw;
            }
            if (IsGlassEnabled()&&Properties.Settings.Default.GlassBackground)
            {
                margins.Top = -1;
                this.Paint += new PaintEventHandler(Nebulae_Paint);
                this.BackColor = transparencyKey;
                VistaApi.DwmExtendFrameIntoClientArea(this.Handle, ref margins);
                
            }

        }

        void Nebulae_Paint(object sender, PaintEventArgs e)
        {
            
        }
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

        }

        private bool IsGlassEnabled()
        {
            if (Environment.OSVersion.Version.Major < 6)
            {
                return false;
            }
            bool isGlassSupported = false;
            VistaApi.DwmIsCompositionEnabled(ref isGlassSupported);
            return isGlassSupported;
        }



        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            propertyGrid.SelectedObject = e.Node.Tag;
        }
        TreeNode entitiesNode, logicNode, sceneNode, aiNode, squadsNode, waypointNode;
        TreeNode characterNode, playerNode, agentsNode;
        List<TreeNode> subNodes, allNodes;
        private void Nebulae_Load(object sender, EventArgs e)
        {

            InitialiseLevelAndNodes();
            subNodes = new List<TreeNode>((new TreeNode[] { entitiesNode, logicNode, squadsNode, waypointNode, playerNode, agentsNode }));
            allNodes = new List<TreeNode>(subNodes);
            allNodes.Add(characterNode);
            allNodes.Add(sceneNode);
            allNodes.Add(aiNode);

            try
            {
                designerID = Properties.Settings.Default.DesignerID;
            }
            catch (NullReferenceException)
            {
                designerID = Guid.NewGuid();
                Properties.Settings.Default.DesignerID = designerID;
                Properties.Settings.Default.Save();
            }
            try
            {
                platform = Properties.Settings.Default.DefaultPlatform;
            }
            catch (NullReferenceException)
            {
                Properties.Settings.Default.DefaultPlatform = TargetPlatform.Windows;
            }
        }

        private void InitialiseLevelAndNodes()
        {
            NewLevel();
            sceneNode = treeView.Nodes["Scene"];
            sceneNode.Name = "Scene";
            logicNode = sceneNode.Nodes["Logic"];
            entitiesNode = sceneNode.Nodes["Entities"];
            sceneNode.Tag = level;
            entitiesNode.Tag = level.SceneGraph.Root.Entities;
            logicNode.Tag = level.Logic;
            aiNode = treeView.Nodes["AI"];
            squadsNode = aiNode.Nodes["Squads"];
            squadsNode.Tag = level.Squads;
            waypointNode = aiNode.Nodes["ManualWaypoints"];
            waypointNode.Tag = level.Waypoints;
            characterNode = treeView.Nodes["Characters"];
            playerNode = characterNode.Nodes["Player"];
            playerNode.Tag = level.PlayerStartInformation;
            agentsNode = characterNode.Nodes["Agents"];
            agentsNode.Tag = level.Agents;
        }

        private void NewLevel()
        {
            level = new Level();
            level.DateCreated = DateTime.Now;
            level.DateLastModified = level.DateCreated;
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Environment.Exit(0);
        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            options.ShowDialog();
        }

        private void levelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            NewLevel();

            PopulateTree();
        }

        private void PopulateTree()
        {
            foreach (TreeNode node in subNodes)
            {
                node.Nodes.Clear();
            }
            InitialiseLevelAndNodes();
            foreach (LogicalEntity ent in level.Logic)
            {
                AddNewEntity(ent, EntityType.Logical);
            }
            foreach (PhysicalEntity ent in level.Entities)
            {
                AddNewEntity(ent, EntityType.Physical);
            }
            foreach (Squad squad in level.Squads)
            {
                AddNewSquad(squad);
            }
            foreach (Waypoint waypoint in level.Waypoints)
            {
                AddNewWaypoint(waypoint);
            }
            foreach (Agent agent in level.Agents)
            {
                AddNewAgent(agent);
            }
            playerNode.Tag = level.PlayerStartInformation;
            propertyGrid.Refresh();
        }

        private void AddNewAgent(Agent agent)
        {
            if (String.IsNullOrEmpty(agent.Name))
            {
                agent.Name = "New Agent";
            }
            TreeNode node = new TreeNode(agent.Name);
            if (!level.Agents.Contains(agent))
            {
                level.Agents.Add(agent);
            }
            node.Tag = agent;
            agentsNode.Nodes.Add(node);
            propertyGrid.Refresh();
        }

        private void AddNewSquad(Squad squad)
        {
            TreeNode node = new TreeNode(squad.Name);
            node.Tag = squad;
            if (!level.Squads.Contains(squad))
            {
                level.Squads.Add(squad);
            }
            squadsNode.Nodes.Add(node);
            propertyGrid.Refresh();
        }

        private void AddNewEntity(Entity ent)
        {
            EntityType et;
            if (ent is LogicalEntity)
            {
                et = EntityType.Logical;
            }
            else if (ent is PhysicalEntity)
            {
                et = EntityType.Physical;
            }
            else
            {
                et = EntityType.Logical;
            }
            AddNewEntity(ent, et);
        }

        private void AddNewEntity(Entity ent, EntityType et)
        {
            string t = "";
            switch (et)
            {
                case EntityType.Logical:
                    t = "Logic";
                    break;
                case EntityType.Physical:
                    t = "Entities";
                    break;
            }
            TreeNode node = new TreeNode(ent.Name);
            node.Tag = ent;
            sceneNode.Nodes[t].Nodes.Add(node);
            propertyGrid.Refresh();
        }

        private void addNewLogicalEntityToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LogicalEntity ent = new LogicalEntity("New logical entity", null);
            AddNewEntity(ent, EntityType.Logical);
            level.Logic.Add(ent);
        }
        enum EntityType
        {
            Logical,
            Physical
        }

        private void propertyGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            if (e.ChangedItem.Label == "Name" && !(allNodes.Contains(treeView.SelectedNode)))
            {
                treeView.SelectedNode.Text = (string)e.ChangedItem.Value;
            }
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.SaveFileDialog sfd = new SaveFileDialog();
            DialogResult dr = sfd.ShowDialog();
            if (dr == DialogResult.OK)
            {
                fileName = sfd.FileName;
                SaveLevel();
            }
        }

        private void SaveLevel()
        {
            level.DateLastModified = DateTime.Now;
            //weaponsDatabase.WriteXml(fileName + ".weapons.nlx");
            xmls.Serialize(new FileStream(fileName, FileMode.Create, FileAccess.Write), level);
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(fileName))
            {
                saveAsToolStripMenuItem_Click(sender, e);
            }
            else
            {
                SaveLevel();
            }
        }

        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                XmlReader reader = XmlReader.Create(ofd.FileName);
                if (xmls.CanDeserialize(reader))
                {
                    level = (Level)xmls.Deserialize(reader);
                    fileName = ofd.FileName;
                    PopulateTree();
                }
            }
            propertyGrid.SelectedObject = treeView.SelectedNode.Tag;
            propertyGrid.Refresh();
        }

        private void addNewEntityToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PhysicalEntity ent = new PhysicalEntity("New entity", null);
            AddNewEntity(ent, EntityType.Physical);
        }

        private void addNewSquadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Squad squad = new Squad("New squad", null);
            AddNewSquad(squad);
        }

        private void addNewWaypointToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddNewWaypoint();
        }

        private void AddNewWaypoint()
        {
            Waypoint waypoint = new Waypoint();
            waypoint.Name = "New waypoint";
            AddNewWaypoint(waypoint);
        }

        private void AddNewWaypoint(Waypoint waypoint)
        {
            TreeNode node = new TreeNode(waypoint.Name);
            node.Tag = waypoint;
            waypointNode.Nodes.Add(node);
            level.Waypoints.Add(waypoint);
            propertyGrid.Refresh();
        }

        private void backgroundCompiler_DoWork(object sender, DoWorkEventArgs e)
        {

        }

        private void addNewAgentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Agent agent = new Agent();
            AddNewAgent(agent);
        }

        private void editWeaponsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WeaponsEditor form = new WeaponsEditor();
            form.Show();
        }

        private void particleSystemsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ParticleEffectDesigner form = new ParticleEffectDesigner();
            form.Show();
        }

        private void materialEditorToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MaterialEditor form = new MaterialEditor();
            form.Show();
        }
    }
}